package club.xiaojiawei.hash;

import java.util.HashSet;

/**
 * @author 肖嘉威
 * @version 1.0
 * @date 4/28/22 9:50 PM
 * @question 202.快乐数
 * @description 编写一个算法来判断一个数 n 是不是快乐数。
 * 「快乐数」 定义为：
 * 对于一个正整数，每一次将该数替换为它每个位置上的数字的平方和。
 * 然后重复这个过程直到这个数变为 1，也可能是 无限循环 但始终变不到 1。
 * 如果这个过程 结果为 1，那么这个数就是快乐数。
 * 如果 n 是 快乐数 就返回 true ；不是，则返回 false 。
 */
public class HappyNumber202 {

    public static void main(String[] args) {
        boolean result = isHappy4(13);
        System.out.println(result);
    }


    public static boolean isHappy(int n) {
        HashSet<Integer> set = new HashSet<>();
        return calc(n, set) == 1;
    }

    /**
     * 递归
     * @param n
     * @param set
     * @return
     */
    public static int calc(int n, HashSet<Integer> set){
        String s = Integer.toString(n);
        int count = 0;
        for (int i = 0; i < s.length(); i++) {
            count += Math.pow(Integer.parseInt(s.substring(i, i + 1)), 2);
        }
        if (count == 1){
            return 1;
        }else if (!set.contains(count)){
            set.add(count);
            return calc(count, set);
        }else {
            return 0;
        }
    }

    /**
     * while
     * @param n
     * @return
     */
    public static boolean isHappy2(int n) {
        HashSet<Integer> set = new HashSet<>();
        int count = n;
        int t;
        while (true){
            String temp = Integer.toString(count);
            count = 0;
            for (int i = 0; i < temp.length(); i++) {
                count += (t = temp.charAt(i) - 48) * t;
            }
            System.out.println(count);
            if (count == 1){
                return true;
            }else if (!set.contains(count)){
                set.add(count);
            }
        }
    }

    /**
     * 找规律
     * 58
     * 89
     * 145
     * 42
     * 20
     * 4
     * 16
     * 37
     * 以上数会重复循环出现
     */
    public static boolean isHappy3(int n) {
        int count = n;
        int t;
        while (true){
            String temp = Integer.toString(count);
            count = 0;
            for (int i = 0; i < temp.length(); i++) {
                count += (t = temp.charAt(i) - 48) * t;
            }
            System.out.println(count);
            if (count == 1){
                return true;
            }else if (count == 58){
                return false;
            }
        }
    }


    /**
     * 双指针(转换成寻找是否有环的问题，弗洛伊德循环查找算法。)
     * @param n
     * @return
     */
    public static boolean isHappy4(int n) {
        int slow = n, fast = squareSum(n);
        while (slow != fast){
            slow = squareSum(slow);
            fast = squareSum(squareSum(fast));
        };
        return slow == 1;
    }

    public static int squareSum(int n) {
        int sum = 0;
        while(n > 0){
            int digit = n % 10;
            sum += digit * digit;
            n /= 10;
        }
        return sum;
    }
}
